package com.gobang.gobangboot.websocket;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.gobang.gobangboot.entity.Game.Point;
import com.gobang.gobangboot.entity.Room.Room;
import com.gobang.gobangboot.entity.Room.RoomData;
import com.gobang.gobangboot.entity.User.User;
import com.gobang.gobangboot.utils.WebSocketUtil;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import org.springframework.stereotype.Component;

import javax.sound.midi.Receiver;
import java.io.IOException;
import java.util.*;

@Component
@ServerEndpoint("/ws/{uname}")
public class WebSocketServer {

    private static Map<String, Session> sessionMap = new HashMap<>();

    private static Map<String, Room> roomMap = new HashMap<>();

    @OnOpen
    public void onOpen(Session session, @PathParam("uname") String uname) throws IOException {
        System.out.println("客户端：" + uname + "建立连接");

        sessionMap.put(uname, session);
    }

    @OnMessage
    public void onMessage(String message, @PathParam("uname") String uname) throws Exception {
        System.out.println("收到来自客户端：" + uname + "的信息：" + message);
        JSONObject entries = JSONUtil.parseObj(message);
        String type = entries.getStr("type");
        Object data = entries.get("data");
        System.out.println(entries);
        if (type.equals("createRoom")){
            createRoom((String) data, uname);
        }
        if (type.equals("roomList")){
            roomList(uname);
        }
        if (type.equals("joinRoom")){
            joinRoom((String) data, uname);
        }
        if (type.equals("leaveRoom")){
            leaveRoom((String) data, uname);
        }
        if (type.equals("ready")){
            ready((String) data, uname);
        }
        if (type.equals("unReady")){
            unReady((String) data, uname);
        }
        if (type.equals("play")){
            play((Map) data);
        }

        if (type.equals("win")){
            win((String) data, uname);
        }
        if (type.equals("message")){
            System.out.println("调用了message方法");
            sendMessage((Map) data, uname);
        }

    }

    @OnClose
    public void onClose(@PathParam("uname") String uname) throws Exception{
        System.out.println("连接断开：" + uname);
        Collection<Room> values = roomMap.values();
        for (Room value : values) {
            if (value.getWhiteName() != null && value.getWhiteName().equals(uname)){
                leaveRoom(value.getRoomName(), uname);
                break;
            }
            if (value.getBlackName() != null && value.getBlackName().equals(uname)){
                leaveRoom(value.getRoomName(), uname);
                break;
            }
        }
        sessionMap.remove(uname);
    }

    public void createRoom(String roomName, String uname) throws IOException {
        Set<Map.Entry<String, Room>> entries = roomMap.entrySet();
        for (Map.Entry<String, Room> entry : entries) {
            if (roomName.equals(entry.getKey())){
                sessionMap.get(uname).getBasicRemote().sendText(WebSocketUtil.getMessage("createRoomError", "房间名冲突！"));
                return;
            }
        }
        Room room = new Room();
        room.setRoomName(roomName);
        room.setRoomStatus("未开始");
        room.setBlackName(uname);
        room.setBlackStatus("未准备");
        room.setNumber(1);
        roomMap.put(roomName, room);
        sessionMap.get(uname).getBasicRemote().sendText(WebSocketUtil.getMessage("createRoomSuccess", roomName));
    }

    public void roomList(String uname) throws Exception {
        Set<Map.Entry<String, Room>> entries = roomMap.entrySet();
        List<RoomData> roomList = new ArrayList<>();
        for (Map.Entry<String, Room> entry : entries) {
            RoomData roomData = new RoomData(entry.getValue().getRoomName(), entry.getValue().getNumber());
            roomList.add(roomData);
        }
        sendMessage(uname, "roomList", roomList);
    }

    public void joinRoom(String roomName, String uname) throws Exception{
        if (roomMap.get(roomName) == null){
            sendMessage(uname, "joinError", "查无此房间");
            return;
        }
        roomMap.get(roomName).setWhiteName(uname);
        roomMap.get(roomName).setWhiteStatus("未准备");
        roomMap.get(roomName).setNumber(2);
        sendMessage(uname, "joinSuccess", roomName);
        sendMessage(roomMap.get(roomName).getWhiteName(), "roomInfo", roomMap.get(roomName));
        sendMessage(roomMap.get(roomName).getBlackName(), "roomInfo", roomMap.get(roomName));

    }

    public void leaveRoom(String roomName, String uname) throws Exception{
        Room room = roomMap.get(roomName);
        room.setNumber(room.getNumber() - 1);
        if (room.getNumber() == 0){
            // 销毁房间
            roomMap.remove(room.getRoomName());
            System.out.println("销毁房间了");
            return;
        }
        if (uname.equals(room.getWhiteName())){
            room.setWhiteName(null);
            room.setWhiteStatus(null);
        }else{
            room.setBlackName(room.getWhiteName());
            room.setBlackStatus(room.getWhiteStatus());
            room.setWhiteName(null);
            room.setWhiteStatus(null);
        }
        sendMessage(room.getBlackName(), "leaveRoom", null);
    }

    public void ready(String roomName, String uname) throws Exception{
        Room room = roomMap.get(roomName);

        if (uname.equals(room.getBlackName())){
            room.setBlackStatus("已准备");
        }
        if (uname.equals(room.getWhiteName())){
            room.setWhiteStatus("已准备");
        }

        if (roomMap.get(roomName).getBlackName() != null){
            sendMessage(room.getBlackName(), "readySuccess", uname);
        }
        if (roomMap.get(roomName).getWhiteName() != null){
            sendMessage(room.getWhiteName(), "readySuccess", uname);
        }

        if (room.getBlackStatus() != null && room.getWhiteStatus() != null){
            if (room.getBlackStatus().equals("已准备") && room.getWhiteStatus().equals("已准备")){
                sendMessage(room.getWhiteName(), "startBattle", room.getBlackName());
                sendMessage(room.getBlackName(), "startBattle", room.getBlackName());
            }
        }


    }

    public void unReady(String roomName, String uname) throws Exception{
        Room room = roomMap.get(roomName);

        if (uname.equals(room.getBlackName())){
            room.setBlackStatus("未准备");
        }
        if (uname.equals(room.getWhiteName())){
            room.setWhiteStatus("未准备");
        }
        if (room.getBlackName() != null){
            sendMessage(room.getBlackName(), "unReadySuccess", uname);
        }
        if (room.getWhiteName() != null){
            sendMessage(room.getWhiteName(), "unReadySuccess", uname);
        }


    }

    public void play(Map map) throws Exception{
        Integer color = (Integer) map.get("color");
        Integer x = (Integer) map.get("x");
        Integer y = (Integer) map.get("y");
        String roomName = (String) map.get("roomName");
        Point point = new Point(x, y, color);
        point.setX(x);
        point.setY(y);
        point.setColor(color);

        if ((Integer) map.get("color") == 1){
            sendMessage(roomMap.get(roomName).getWhiteName(), "play", point);
        }
        if ((Integer) map.get("color") == 2){
            sendMessage(roomMap.get(roomName).getBlackName(), "play", point);
        }
    }

    public void win(String roomName, String uname) throws Exception{
        Room room = roomMap.get(roomName);
        sendMessage(room.getBlackName(), "win", uname);
        sendMessage(room.getWhiteName(), "win", uname);
    }

    public void sendMessage(Map data, String uname) throws Exception{
        String roomName = (String) data.get("roomName");
        String message = (String) data.get("message");
        Map sendData = new HashMap();
        sendData.put("username", uname);
        sendData.put("message", message);

        Room room = roomMap.get(roomName);
        if (room.getBlackName() != null){
            sessionMap.get(room.getBlackName()).getBasicRemote().sendText(WebSocketUtil.getMessage("message", sendData));
        }
        if (room.getWhiteName() != null){
            sessionMap.get(room.getWhiteName()).getBasicRemote().sendText(WebSocketUtil.getMessage("message", sendData));
        }
    }

    public void sendMessage(String uname, String type, Object data) throws Exception {
        sessionMap.get(uname).getBasicRemote().sendText(WebSocketUtil.getMessage(type, data));
    }





}
